package com.bestcem.xm.component.mybatis.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

import static com.baomidou.mybatisplus.core.toolkit.Constants.WRAPPER_PARAM;

/**
 * @ClassName: XmService
 * @Description:
 * @Author: chenglong.yue
 * @Date: 2022/7/26 16:44
 */
public interface IXmService<T> extends IService<T> {

    /**
     * 变量占位符正则
     */
    Pattern PARAM_PAIRS_RE = Pattern.compile("#\\{ew\\.paramNameValuePairs\\.(" + WRAPPER_PARAM + "\\d+)}");

    default int count(String content, String strForSearch) {
        //if (ObjectUtils.isEmpty(content) || ObjectUtils.isEmpty(content) || strForSearch.length() > content.length()) {
        //    return 0;
        //}
        //
        //int count = 0;
        //int idx = 0;
        //while ((idx = content.indexOf(strForSearch, idx)) > -1) {
        //    count++;
        //    idx += strForSearch.length();
        //}
        //return count;

        return StringUtils.countOccurrencesOf(content, strForSearch);
    }

    default String[] getNullPropertyNames(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<>();
        for (java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) {
                emptyNames.add(pd.getName());
            }
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }

    /**
     * 非空属性复制
     *
     * @param src
     * @param target
     * @author chenglong.yue <chenglong.yue@idiaoyan.com>
     * @date 2023/3/16 10:58
     */
    default void copyProperties(Object src, Object target) {
        BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
    }

    boolean saveBatch(Collection<T> entityList, int batchSize);

    /*public void test() throws Exception {
        SurveyUniqueAnswer query = new SurveyUniqueAnswer();
        query.setProjectId("62d7c449aace700008543984");
        query.setSeq(67015548L);
        query.setQid(23);
        query.setRowId(0);
        query.setData("鸡巴.com");
        query.setOpId(13);
        //eq属性必须这样写，否则后面queryWrapper.getEntity()为null
        //可以queryWrapper.getEntity()为null时，queryWrapper.getParamNameValuePairs()，反射设置属性，这样会有性能损耗，所以没写
        LambdaQueryWrapper<SurveyUniqueAnswer> queryWrap = new LambdaQueryWrapper<>(query);
        //其他非eq的where条件写这里
        queryWrap.in(SurveyUniqueAnswer::getVersionId, 1, 2, 3);

        //需要更新的
        SurveyUniqueAnswer update = new SurveyUniqueAnswer();
        update.setData("网吧.com");

        SurveyUniqueAnswer uniq_ans = surveyUniqueAnswerService.getOneAndUpdate(queryWrap, update, Boolean.TRUE);
        System.out.println(uniq_ans);
    }*/

    /**
     * 模仿python get_one_and_update
     * args[0]（对应python的_upsert）是true时，且queryWrapper没查到会将queryWrapper中eq的属性和update属性组装一起insert，默认为False
     * args[1]（对应python的return_before）为True时返回更新前对象(如果没查到返回null)，默认为False
     *
     * @param queryWrapper where查询条件
     * @param update       需要更新的属性
     * @param args         可变参数，对应python的_upsert、return_before
     * @return T
     * @author chenglong.yue <chenglong.yue@idiaoyan.com>
     * @date 2023/3/2 13:56
     */
    T getOneAndUpdate(LambdaQueryWrapper<T> queryWrapper, T update, Boolean... args) throws Exception;

    /**
     * 自动构建查询条件，只支持eq和in，其他的自己手写
     */
    QueryWrapper<T> getQueryWrapperEqOrIn(Class<?> clazz, JSONObject param, List<String> cols);
}
